﻿using BJoin.Application.BObject;
using BJoin.Application.Entity;
using BJoin.DapperExtension.DatabaseFactory;
using BJoin.DapperExtension.Postgresql.TypeHandler;
using Dapper;
using DapperExtensions;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BJoin.Application.IRepository
{
    public abstract class BaseFactoryRepository<T, TKey, TExt> : IBaseRepository<T, TKey, TExt> where T : Entity<TKey, TExt> where TExt : BObjExt
    {

        protected BaseFactoryRepository(ILogger<BaseFactoryRepository<T, TKey, TExt>> logger, IDbFactory<IDatabase, long?> factory)
        {
            SqlMapper.AddTypeHandler(typeof(TExt), new JsonTypeHandler<TExt>());
        }
        #region 异步
        public virtual async Task<long> CountAsync(IDatabase database, object predicate = null)
        {
            return await database.CountAsync<T>(predicate);
        }
        public virtual async Task<long> CountByComplexSqlAsync(IDatabase database, string sql, object param = null)
        {
            return await database.CountByComplexSqlAsync(sql, param);
        }
        public virtual async Task<T> GetAsync(IDatabase database, TKey id)
        {
            return await database.GetAsync<T>(id);
        }
        public virtual async Task<IEnumerable<T>> GetListAsync(IDatabase database, object predicate = null, string[] sorts = null)
        {
            return await database.GetListAsync<T>(predicate, RepositoryHelper.OrderByToSort<T>(sorts));
        }
        public virtual async Task<Page<T>> GetListPagingAsync(IDatabase database, int pageNumber, int recordsPerPage, object predicate = null, string[] sorts = null)
        {
            return await database.GetPagesAsync<T>(pageNumber, recordsPerPage, predicate, RepositoryHelper.OrderByToSort<T>(sorts));
        }

        public virtual async Task<IEnumerable<T>> GetListSetAsync(IDatabase database, int firstResult, int maxResults, object predicate = null, string[] sorts = null)
        {
            return await database.GetSetAsync<T>(predicate, RepositoryHelper.OrderByToSort<T>(sorts), firstResult, maxResults);
        }

        public virtual async Task<IEnumerable<TR>> GetListByComplexSqlAsync<TR>(IDatabase database, string sql, object param=null) where TR:class
        {
            return await database.GetListByComplexSqlAsync<TR>(sql,param);
        }
        public virtual async Task<Page<TR>> GetListPagingByComplexSqlAsync<TR>(IDatabase database, int pageNumber, int recordsPerPage, string sql, object param = null) where TR : class
        {
            return await database.GetPagesByComplexSqlAsync<TR>(sql,param,pageNumber,recordsPerPage);
        }
        public virtual async Task<TKey> InsertAsync(IDatabase database, T entity)
        {
            return await database.InsertAsync(entity);
        }
        public virtual async Task<IEnumerable<TKey>> InsertManyAsync(IDatabase database, IEnumerable<T> entities)
        {
            await database.InsertAsync(entities);
            return entities.Select(e => e.Id);
        }
        public virtual async Task<bool> UpdateAsync(IDatabase database, T entity, object predicate)
        {
            return await database.UpdateAsync<T>(entity, predicate);
        }
        public virtual async Task<bool> UpdateSetAsync(IDatabase database, T entity, object predicate)
        {
            return await database.UpdateSetAsync<T>(entity, predicate);
        }
        public virtual async Task<bool> DeleteAsync(IDatabase database, TKey id)
        {
            return await database.DeleteAsync<T>(new { Id = id });
        }

        public virtual async Task<bool> DeleteAsync(IDatabase database, object predicate = null)
        {
            RepositoryHelper.ObjectNotNull(predicate);
            return await database.DeleteAsync<T>(predicate);
        }
        public virtual async Task<bool> DeleteAsync(IDatabase database, string ids)
        {
            return await database.DeleteAsync<T>(new { Id = ids.Split(',') });
        }
        #endregion
    }
}
